using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;

namespace CodeStream.Testing.WebAutomation
{
    /// <summary>
    /// Helper methods to aid in converting names and tags into identifiers and UI Testing classes
    /// </summary>
    internal static class HelperExtensions
    {
        private static readonly Dictionary<string, Type> s_tagMapping = new Dictionary<string, Type>
        {
            { "AREA", typeof(HtmlAreaHyperlink) },
            { "BUTTON", typeof(HtmlButton) },
            { "TD", typeof(HtmlCell) },
            { "INPUT[TYPE='CHECKBOX']", typeof(HtmlCheckBox) },
            { "DIV", typeof(HtmlDiv) },
            { "BODY", typeof(HtmlDocument) },
            { "INPUT[TYPE='TEXT']", typeof(HtmlEdit) },
            { "INPUT[TYPE='FILE']", typeof(HtmlFileInput) },
            { "FRAME", typeof(HtmlFrame) },
            { "TH", typeof(HtmlHeaderCell) },
            { "A", typeof(HtmlHyperlink) },
            { "IFRAME", typeof(HtmlIFrame) },
            { "IMG", typeof(HtmlImage) },
            { "INPUT[TYPE='BUTTON']", typeof(HtmlInputButton) },
            { "LABEL", typeof(HtmlLabel) },
            { "SELECT", typeof(HtmlList) },
            { "OPTION", typeof(HtmlListItem) },
            { "INPUT[TYPE='RADIO']", typeof(HtmlRadioButton) },
            { "TR", typeof(HtmlRow) },            
            { "SPAN", typeof(HtmlSpan) },
            { "TABLE", typeof(HtmlTable) },
            { "TEXTAREA", typeof(HtmlTextArea) }
        };

        /// <summary>
        /// Converts names to valid .NET identifiers.
        /// </summary>
        /// <remarks>
        /// The schema validation takes care of most of the formatting, what's left is convert spaces to underscores.
        /// </remarks>
        /// <param name="name">The name to convert to a valid identifier.</param>
        /// <returns>The properly formatted .NET identifier.</returns>
        public static string ToIdentifier(this string name)
        {
            Contract.Requires(name != null);
            Contract.Ensures(Contract.Result<string>() != null);

            return name.Replace(' ', '_');
        }

        /// <summary>
        /// Converts an HTML tag to a .NET type representing the UI test class for the tag.
        /// </summary>
        /// <param name="tagName">Name of the HTML tag.</param>
        /// <returns>The type of .NET UI test class representing the tag.</returns>
        public static Type ConvertToType(this string tagName)
        {
            Contract.Requires(!string.IsNullOrEmpty(tagName));
            Contract.Ensures(Contract.Result<Type>() != null);

            Type result = null;
            if (!s_tagMapping.TryGetValue(tagName.ToUpperInvariant(), out result))
                result = typeof(HtmlCustom);
            Contract.Assume(result != null); // no valid lookups have a value of null

            return result;
        }
    }
}
